﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace TimeSolve
{
    public class CreatGeometry
    {
        public Viewport3D testGeom()
        {
            // Declare scene objects.
            Viewport3D myViewport3D = new Viewport3D();
            Model3DGroup myModel3DGroup = new Model3DGroup();
            GeometryModel3D myGeometryModel = new GeometryModel3D();
            ModelVisual3D myModelVisual3D = new ModelVisual3D();
    
            OrthographicCamera myPCamera = new OrthographicCamera();
            myPCamera.Position = new Point3D(0, 0, 2000);
            myPCamera.LookDirection = new Vector3D(0, 0, -1);
            myPCamera.UpDirection = new Vector3D(0, 1, 0);
            myPCamera.Width = 2;
            myViewport3D.Camera = myPCamera;

            AmbientLight light = new AmbientLight();
            light.Color = Colors.White;
       
            myModel3DGroup.Children.Add(light);
            

            MeshGeometry3D myMeshGeometry3D
                = Cylinder(new Point3D(0, 0, 0), new Vector3D(1, 0, 0), new Vector3D(0, 0, 1), 8);
               // = BoxOut(new Point3D(-1, -1, -1), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0), new Vector3D(0, 0, 1));
                //= Plane2_simple(new Point3D(0, 0, 0),
                //new List<Vector3D>() { new Vector3D(1, 0, 0), new Vector3D(0, 1, 0),new Vector3D(-1,0,0) });

            myGeometryModel.Geometry = myMeshGeometry3D;
 
            SolidColorBrush brush = Brushes.Orange;
            DiffuseMaterial myMaterial = new DiffuseMaterial(brush);
            myGeometryModel.Material = myMaterial;


            RotateTransform3D myRotateTransform3D = new RotateTransform3D();
            AxisAngleRotation3D myAxisAngleRotation3d = new AxisAngleRotation3D();
            myAxisAngleRotation3d.Axis = new Vector3D(0, 3, 0);
            myAxisAngleRotation3d.Angle = 0;
            myRotateTransform3D.Rotation = myAxisAngleRotation3d;
            myGeometryModel.Transform = myRotateTransform3D;

            // Add the geometry model to the model group.
            myModel3DGroup.Children.Add(myGeometryModel);

            // Add the group of models to the ModelVisual3d.
            myModelVisual3D.Content = myModel3DGroup;

            // 
            myViewport3D.Children.Add(myModelVisual3D);

            // Apply the viewport to the page so it will be rendered.
            return myViewport3D;
        }
        
        public Model3DGroup SimpleCoordinateTest()
        {
            Model3DGroup modelgroup = new Model3DGroup();
            //DirectionalLight light = new DirectionalLight()
            //{
            //    Color = Colors.White,
            //    Direction = new Vector3D(0, 0, -1)
            //};
            GeometryModel3D basebox = new GeometryModel3D()
            {
                Geometry = LineBase (),
                Material = new DiffuseMaterial(Brushes.Black)
            };
     
   
           // modelgroup.Children.Add(MeshRenderLib.AddLights(new Vector3D(0,0,-1),130,160));
            modelgroup.Children.Add(basebox);
   
            //Viewport3D geo = new Viewport3D()
     
            return modelgroup;
        }
        public Viewport3D SimpleCoordinate()
        {
            Model3DGroup modelgroup = new Model3DGroup();
            AmbientLight light = new AmbientLight()
            {
                Color = Colors.White
            };
            GeometryModel3D basebox = new GeometryModel3D()
            {
                Geometry = BoxOut(new Point3D(-2, -2, -2), new Vector3D(4, 0, 0), new Vector3D(0, 4, 0), new Vector3D(0, 0, 4)),
                Material = new DiffuseMaterial(Brushes.Black)
            };
          
            Geometry3D axis1 = Cylinder(new Point3D(0, 0, 0), new Vector3D(18, 0, 0), new Vector3D(0, 0, 1), 8);
            Geometry3D axis2 = Cone(new Point3D(17, 0, 0), new Vector3D(8, 0, 0), new Vector3D(0, 0, 4), 8);
            DiffuseMaterial redm = new DiffuseMaterial(Brushes.Red);
            GeometryModel3D ax1 = new GeometryModel3D()
            {
                Geometry = axis1,
                Material =redm
            };
            GeometryModel3D ax2 = new GeometryModel3D()
            {
                Geometry = axis2,
                Material = redm
            };
            RotateTransform3D rtoy = new RotateTransform3D() 
            {
                Rotation = new AxisAngleRotation3D() 
                {
                    Axis = new Vector3D(0, 0, 1),
                    Angle = 90
                }
            };
            DiffuseMaterial greenm = new DiffuseMaterial(Brushes.Green );
            GeometryModel3D ay1 = new GeometryModel3D()
            {
                Geometry = axis1,
                Material = greenm,
                Transform = rtoy
            };
            GeometryModel3D ay2 = new GeometryModel3D()
            {
                Geometry = axis2,
                Material = greenm,
                Transform = rtoy
            };
            RotateTransform3D rtoz = new RotateTransform3D()
            {
                Rotation = new AxisAngleRotation3D()
                {
                    Axis = new Vector3D(0, 1, 0),
                    Angle = -90
                }
            };
            DiffuseMaterial bluem = new DiffuseMaterial(Brushes.Blue );
            GeometryModel3D az1 = new GeometryModel3D()
            {
                Geometry = axis1,
                Material = bluem,
                Transform = rtoz
            };
            GeometryModel3D az2 = new GeometryModel3D()
            {
                Geometry = axis2,
                Material = bluem,
                Transform = rtoz
            };
            modelgroup.Children.Add(light);
            modelgroup.Children.Add(basebox);
            modelgroup.Children.Add(ax1);
            modelgroup.Children.Add(ax2);
            modelgroup.Children.Add(ay1);
            modelgroup.Children.Add(ay2);
            modelgroup.Children.Add(az1);
            modelgroup.Children.Add(az2);     
            Viewport3D geo = new Viewport3D()
            {
                Camera = new OrthographicCamera()
                {
                    Position = new Point3D(0, 0, 600),
                    LookDirection = new Vector3D(0, 0, -600),
                    Width = 70,
                    UpDirection = new Vector3D(0, 1, 0)
                }                
            };
            geo.Children.Add(new ModelVisual3D() { Content=modelgroup});
            return geo;
        }
        public  Model3DGroup createArrow()
        {
            Model3DGroup modelgroup = new Model3DGroup();
            Geometry3D axis1 = Cylinder(new Point3D(0, 0, 0), new Vector3D(0, 0, 18), new Vector3D(1, 0, 0), 4);
            Geometry3D axis2 = Cone(new Point3D(0, 0, 17), new Vector3D(0, 0, 8), new Vector3D(4, 0, 0), 4);
            DiffuseMaterial redm = new DiffuseMaterial(Brushes.Red);
            GeometryModel3D ax1 = new GeometryModel3D()
            {
                Geometry = axis1,
                Material = redm
            };
            GeometryModel3D ax2 = new GeometryModel3D()
            {
                Geometry = axis2,
                Material = redm
            };
            modelgroup.Children.Add(ax1);
            modelgroup.Children.Add(ax2);
            return modelgroup;
        }
        public ModelVisual3D creatCoordinateModel()
        {
            Model3DGroup modelgroup = new Model3DGroup();
            AmbientLight light = new AmbientLight()
            {
                Color = Colors.White
            };
            GeometryModel3D basebox = new GeometryModel3D()
            {
                Geometry = BoxOut(new Point3D(-2, -2, -2), new Vector3D(4, 0, 0), new Vector3D(0, 4, 0), new Vector3D(0, 0, 4)),
                Material = new DiffuseMaterial(Brushes.Black)
            };
            Geometry3D axis1 = Cylinder(new Point3D(0, 0, 0), new Vector3D(18, 0, 0), new Vector3D(0, 0, 1), 8);
            Geometry3D axis2 = Cone(new Point3D(17, 0, 0), new Vector3D(8, 0, 0), new Vector3D(0, 0, 4), 8);
            DiffuseMaterial redm = new DiffuseMaterial(Brushes.Red);
            GeometryModel3D ax1 = new GeometryModel3D()
            {
                Geometry = axis1,
                Material = redm
            };
            GeometryModel3D ax2 = new GeometryModel3D()
            {
                Geometry = axis2,
                Material = redm
            };
            RotateTransform3D rtoy = new RotateTransform3D()
            {
                Rotation = new AxisAngleRotation3D()
                {
                    Axis = new Vector3D(0, 0, 1),
                    Angle = 90
                }
            };
            DiffuseMaterial greenm = new DiffuseMaterial(Brushes.Green);
            GeometryModel3D ay1 = new GeometryModel3D()
            {
                Geometry = axis1,
                Material = greenm,
                Transform = rtoy
            };
            GeometryModel3D ay2 = new GeometryModel3D()
            {
                Geometry = axis2,
                Material = greenm,
                Transform = rtoy
            };
            RotateTransform3D rtoz = new RotateTransform3D()
            {
                Rotation = new AxisAngleRotation3D()
                {
                    Axis = new Vector3D(0, 1, 0),
                    Angle = -90
                }
            };
            DiffuseMaterial bluem = new DiffuseMaterial(Brushes.Blue);
            GeometryModel3D az1 = new GeometryModel3D()
            {
                Geometry = axis1,
                Material = bluem,
                Transform = rtoz
            };
            GeometryModel3D az2 = new GeometryModel3D()
            {
                Geometry = axis2,
                Material = bluem,
                Transform = rtoz
            };
            modelgroup.Children.Add(light);
            modelgroup.Children.Add(basebox);
            modelgroup.Children.Add(ax1);
            modelgroup.Children.Add(ax2);
            modelgroup.Children.Add(ay1);
            modelgroup.Children.Add(ay2);
            modelgroup.Children.Add(az1);
            modelgroup.Children.Add(az2);
 
            return new ModelVisual3D() { Content = modelgroup };
        }
        public MeshGeometry3D Plane2_simple(Point3D startpoint,List<Vector3D> sides)
        {
            MeshGeometry3D plane = new MeshGeometry3D();

            Point3DCollection vertexs = new Point3DCollection();
            vertexs.Add(startpoint);
            Point3D pkeep = startpoint;
            foreach(Vector3D v in sides)
            {
                pkeep += v;
                vertexs.Add(pkeep);
            }
            plane.Positions = vertexs;

            Int32Collection TriangleIndices = new Int32Collection();
            for(int i = 0; i < vertexs.Count - 2; i++)
            {
                TriangleIndices.Add(0);
                TriangleIndices.Add(i+1);
                TriangleIndices.Add(i+2);
                //TriangleIndices.Add(0);
                //TriangleIndices.Add(i + 2);
                //TriangleIndices.Add(i + 1);
            }
            for (int i = 0; i < vertexs.Count - 2; i++)
            {
                TriangleIndices.Add(0);
                TriangleIndices.Add(i + 2);
                TriangleIndices.Add(i + 1);
            }
            plane.TriangleIndices = TriangleIndices;

            return plane;
        }
        public MeshGeometry3D BoxOut(Point3D startpoint, Vector3D vx,Vector3D vy,Vector3D vz)
        {//vx,vy,vz方向可能导致出错
            MeshGeometry3D box = new MeshGeometry3D();

            Point3DCollection vertexs = new Point3DCollection();
            vertexs.Add(startpoint);
            vertexs.Add(startpoint + vx);
            int n = vertexs.Count;
            for  (int i=0;i<n;i++)
            {
                vertexs.Add(vertexs[i] + vy);
            }
            n = vertexs.Count;
            for (int i = 0; i < n; i++)
            {
                vertexs.Add(vertexs[i] + vz);
            }
            box.Positions = vertexs;

            Int32Collection TriangleIndices = new Int32Collection();
            Action<Int32Collection, int, int, int, int> indice
                = (col,a, b, c, d) =>
            {
                col.Add(a);
                col.Add(b);
                col.Add(c);
                col.Add(a); 
                col.Add(c);
                col.Add(d);
            };
            calPlane1(ref TriangleIndices, 2, 3, 1, 0);
            calPlane1(ref TriangleIndices, 7, 6, 4, 5);
            calPlane1(ref TriangleIndices, 1, 3, 7, 5);
            calPlane1(ref TriangleIndices, 3, 2, 6, 7);
            calPlane1(ref TriangleIndices, 2, 0, 4, 6);
            calPlane1(ref TriangleIndices, 0, 1, 5, 4);
            box.TriangleIndices = TriangleIndices;
            return box;
        }
        private void calPlane1(ref Int32Collection col,int a,int b,int c,int d)
        {//a,b,c,d逆时针旋转
            col.Add(a);
            col.Add(b);
            col.Add(c);
            col.Add(a);
            col.Add(c);
            col.Add(d);
        }
      
        public  MeshGeometry3D Cylinder(Point3D basepoint,Vector3D axis,Vector3D r,int n)
        {         
            MeshGeometry3D geo = new MeshGeometry3D();
            //添加点
            Point3DCollection vertexs = new Point3DCollection();
            vertexs.Add(basepoint);
            vertexs.Add(basepoint + r);//边上第一个点已经有了
            Vector3D vertical = Vector3D.CrossProduct(r, axis);
            vertical = vertical * (r.Length / vertical.Length);
            for (int i = 1; i < n; i++)
            {
                double radian = Math.PI * 2 / n * i;
                Vector3D vi = Math.Cos(radian) * r + Math.Sin(radian) * vertical;
                vertexs.Add(basepoint + vi);
            }
            for (int i = 0; i < n+1; i++)
            {
                vertexs.Add(vertexs[i] + axis);
            }
            geo.Positions = vertexs;
            //添加三角
            Int32Collection Tri= new Int32Collection();
            for(int i = 1; i < n ; i++)
            {
                Tri.Add(0);
                Tri.Add(i);
                Tri.Add(i + 1);
            }
            Tri.Add(0);
            Tri.Add(n);
            Tri.Add(1);
            for (int i = 1; i < n; i++)
            {
                Tri.Add(n + 1);
                Tri.Add(n + i + 2);
                Tri.Add(n + i + 1);
            }
            Tri.Add(n + 1);
            Tri.Add(n + 2);
            Tri.Add(n + n + 1);
            for(int i = 1; i < n; i++)
            {
                calPlane1(ref Tri, i, i + n + 1, i + n + 2, i + 1);
            }
            calPlane1(ref Tri, n, n + n + 1, n + 2, 1);
            geo.TriangleIndices = Tri;



            return geo;
        }
        public MeshGeometry3D Cone(Point3D basepoint, Vector3D axis, Vector3D r, int n)
        {
            MeshGeometry3D geo = new MeshGeometry3D();
            //添加点
            Point3DCollection vertexs = new Point3DCollection();
            vertexs.Add(basepoint);
            vertexs.Add(basepoint + r);//边上第一个点已经有了
            Vector3D vertical = Vector3D.CrossProduct(r, axis);
            vertical = vertical * (r.Length / vertical.Length);
            for (int i = 1; i < n; i++)
            {
                double radian = Math.PI * 2 / n * i;
                Vector3D vi = Math.Cos(radian) * r + Math.Sin(radian) * vertical;
                vertexs.Add(basepoint + vi);
            }
            vertexs.Add(basepoint + axis);
            geo.Positions = vertexs;
            //添加三角
            Int32Collection Tri = new Int32Collection();
            for (int i = 1; i < n; i++)
            {
                Tri.Add(0);
                Tri.Add(i);
                Tri.Add(i + 1);

                Tri.Add(n + 1);
                Tri.Add(i + 1);
                Tri.Add(i);
            }
            Tri.Add(0);
            Tri.Add(n);
            Tri.Add(1);
            Tri.Add(n+1);
            Tri.Add(1);
            Tri.Add(n);
            geo.TriangleIndices = Tri;
            return geo;
        }


        public MeshGeometry3D LineBase()
        {
            Point3DCollection points = new Point3DCollection();
            points.Add(new Point3D(-0.5, -0.29, 0));
            points.Add(new Point3D(-0.5, -0.29, 1));

            points.Add(new Point3D(0.5, -0.29, 0));
            points.Add(new Point3D(0.5, -0.29, 1));

            points.Add(new Point3D(0, 0.58, 0));         
            points.Add(new Point3D(0, 0.58, 1));
            Int32Collection triangles = new Int32Collection();
            triangles.Add(0);
            triangles.Add(2);
            triangles.Add(3);
            triangles.Add(0);
            triangles.Add(3);
            triangles.Add(1);

            triangles.Add(2);
            triangles.Add(4);
            triangles.Add(5);
            triangles.Add(2);
            triangles.Add(5);
            triangles.Add(3);

            triangles.Add(4);
            triangles.Add(0);
            triangles.Add(1);
            triangles.Add(4);
            triangles.Add(1);
            triangles.Add(5);          
            return new MeshGeometry3D() { Positions = points, TriangleIndices = triangles };
        }
        public MeshGeometry3D LineBase2()
        {
            Point3DCollection points = new Point3DCollection();
            points.Add(new Point3D(-0.5, -0.5, 0));
            points.Add(new Point3D(-0.5, -0.5, 1));
            points.Add(new Point3D(0.5, -0.5, 0));
            points.Add(new Point3D(0.5, -0.5, 1));
            points.Add(new Point3D(0.5, 0.5, 0));
            points.Add(new Point3D(0.5, 0.5, 1));
            points.Add(new Point3D(-0.5, 0.5, 0));
            points.Add(new Point3D(-0.5, 0.5, 1));
            Int32Collection triangles = new Int32Collection();
            triangles.Add(0);
            triangles.Add(2);
            triangles.Add(3);
            triangles.Add(0);
            triangles.Add(3);
            triangles.Add(1);

            triangles.Add(2);
            triangles.Add(4);
            triangles.Add(5);
            triangles.Add(2);
            triangles.Add(5);
            triangles.Add(3);

            triangles.Add(4);
            triangles.Add(6);
            triangles.Add(7);
            triangles.Add(4);
            triangles.Add(7);
            triangles.Add(5);

            triangles.Add(6);
            triangles.Add(0);
            triangles.Add(1);
            triangles.Add(6);
            triangles.Add(1);
            triangles.Add(7);

            return new MeshGeometry3D() { Positions = points, TriangleIndices = triangles };
        }
    }

}


//public Model3DGroup SimpleCoordinateTest()
//{
//    Model3DGroup modelgroup = new Model3DGroup();
//    //DirectionalLight light = new DirectionalLight()
//    //{
//    //    Color = Colors.White,
//    //    Direction = new Vector3D(0, 0, -1)
//    //};
//    GeometryModel3D basebox = new GeometryModel3D()
//    {
//        Geometry = BoxOut(new Point3D(-2, -2, -2), new Vector3D(4, 0, 0), new Vector3D(0, 4, 0), new Vector3D(0, 0, 4)),
//        Material = new DiffuseMaterial(Brushes.Black)
//    };
//    Geometry3D axis1 = Cylinder(new Point3D(0, 0, 0), new Vector3D(18, 0, 0), new Vector3D(0, 0, 1), 8);
//    Geometry3D axis2 = Cone(new Point3D(17, 0, 0), new Vector3D(8, 0, 0), new Vector3D(0, 0, 4), 8);
//    Material mred = BuildGraph.getMetalMaterial(Brushes.Red, 255, 255);
//    Material mgreen = BuildGraph.getMetalMaterial(Brushes.Green, 255, 255);
//    Material mblue = BuildGraph.getMetalMaterial(Brushes.Blue, 255, 255);
//    GeometryModel3D ax1 = new GeometryModel3D()
//    {
//        Geometry = axis1,
//        Material = mred
//    };
//    GeometryModel3D ax2 = new GeometryModel3D()
//    {
//        Geometry = axis2,
//        Material = mred
//    };
//    GeometryModel3D planetest = new GeometryModel3D()
//    {
//        Geometry = Plane2_simple(new Point3D(0, 0, 0), new List<Vector3D> { new Vector3D(30, 30, 0), new Vector3D(0, 0, 30), new Vector3D(-30, -30, 0) }),
//        Material = mred
//    };
//    RotateTransform3D rtoy = new RotateTransform3D()
//    {
//        Rotation = new AxisAngleRotation3D()
//        {
//            Axis = new Vector3D(0, 0, 1),
//            Angle = 90
//        }
//    };
//    GeometryModel3D ay1 = new GeometryModel3D()
//    {
//        Geometry = axis1,
//        Material = mgreen,
//        Transform = rtoy
//    };
//    GeometryModel3D ay2 = new GeometryModel3D()
//    {
//        Geometry = axis2,
//        Material = mgreen,
//        Transform = rtoy
//    };
//    GeometryModel3D ay2t = new GeometryModel3D()
//    {
//        Geometry = axis2,
//        Material = new DiffuseMaterial(Brushes.Orange),
//        Transform = rtoy
//    };
//    RotateTransform3D rtoz = new RotateTransform3D()
//    {
//        Rotation = new AxisAngleRotation3D()
//        {
//            Axis = new Vector3D(0, 1, 0),
//            Angle = -90
//        }
//    };
//    GeometryModel3D az1 = new GeometryModel3D()
//    {
//        Geometry = axis1,
//        Material = mblue,
//        Transform = rtoz
//    };
//    GeometryModel3D az2 = new GeometryModel3D()
//    {
//        Geometry = axis2,
//        Material = mblue,
//        Transform = rtoz
//    };
//    // modelgroup.Children.Add(MeshRenderLib.AddLights(new Vector3D(0,0,-1),130,160));
//    modelgroup.Children.Add(basebox);
//    modelgroup.Children.Add(ax1);
//    modelgroup.Children.Add(ax2);
//    modelgroup.Children.Add(ay1);
//    modelgroup.Children.Add(ay2);
//    modelgroup.Children.Add(ay2t);
//    modelgroup.Children.Add(az1);
//    modelgroup.Children.Add(az2);
//    modelgroup.Children.Add(planetest);
//    //Viewport3D geo = new Viewport3D()
//    //{
//    //    Camera = new OrthographicCamera()
//    //    {
//    //        Position = new Point3D(0, 0, 600),
//    //        LookDirection = new Vector3D(0, 0, -600),
//    //        Width = 70,
//    //        UpDirection = new Vector3D(0, 1, 0)
//    //    }
//    //};
//    //geo.Children.Add(new ModelVisual3D() { Content = modelgroup });
//    return modelgroup;
//}